/**
 * @file   DocHeader.java
 * @author Enrique Madrid <e.madrid@lpcsite.com>
 * @date   Tue Sep 18 10:48:59 2007
 * 
 * @brief  
 * 
 * 
 */
package sim.framework.modules.business;

import java.util.*;

import sim.framework.*;
import sim.store.*;
import sim.utils.*;

public abstract class DocHeader extends Document {

    public static final int FIELD_PRIMARYKEY = 0;
    public static final int FIELD_ADMINSTATE = 1;
    public static final int FIELD_CREATEDAGE = 2;
    public static final int FIELD_UPDATEDAGE = 3;
    public static final int FIELD_MODULETYPE = 4;
    public static final int FIELD_NUMARCHDET = 5;
    public static final int FIELD_TOTAL = 6;

    private String m_Filename = null;
    private DataTxt m_Record = null;
    private Vector m_Details = new Vector(1);

    /**
     * CONSTRUCTORES
     * 
     */

    public DocHeader(Simlet s, final String filename) {
	super(s);
	m_Record = new DataTxt(Utils.TOKEN, Utils.TOKEN_PIPE, 1, 
			       DocHeader.FIELD_TOTAL, 
			       s.getAppEncoding());
	m_Filename = filename;
    }

    public final void appendDetail(final DocDetail docDetail) {
	docDetail.setDocHeader(this);
	m_Details.addElement(docDetail);
    }

    /**
     * CAMPOS
     * 
     */
    private void setPrimaryKey() {
	if (m_Record.empty(FIELD_PRIMARYKEY)) {
	    m_Record.set(FIELD_PRIMARYKEY, getNextRecordId(), 10);
	}
    }

    public final byte[] getPrimaryKey() {
	return m_Record.getBytes(FIELD_PRIMARYKEY);
    }

    protected void setCreateAge() {
	if (empty(FIELD_CREATEDAGE)) {
	    m_Record.set(FIELD_CREATEDAGE, m_Simlet.currentTimeSeconds(), 16);
	}
    }

    private void setUpdateAge() {
	m_Record.set(FIELD_UPDATEDAGE, m_Simlet.currentTimeSeconds(), 16);
    }
    
    public final String getCreateDate() {
	// Falta usar calendar.
	return null;
    }

    public final String getUpdateDate() {
	// Falta usar calendar.
	return null;
    }

    public final void setModuleId(int moduleId) {
	m_Record.set(FIELD_MODULETYPE, moduleId, 16);
    }

    public final int getModuleId() {
	return Utils.memtoul(getBytes(FIELD_MODULETYPE), 16);
    }

    private void setNumArchDetails() {
	if (m_Record.empty(FIELD_NUMARCHDET)) {
	    m_Record.set(FIELD_NUMARCHDET, m_Details.size(), 10);
	}
    }

    public final int getNumArchDetails() {
	return Utils.memtoul(m_Record.getBytes(FIELD_NUMARCHDET), 10);
    }

    private void setNumItemsByDetail() {
	Enumeration e;
	DocDetail docDetail;
	int j;

	j = FIELD_TOTAL;

	e = m_Details.elements();
	while (e.hasMoreElements()) {
	    docDetail = (DocDetail)e.nextElement();
	    m_Record.set(j++, docDetail.getItems().size(), 10);
	}

    }

    public final int getNumItemsByDetail(int index) {
	if (index < getNumArchDetails()) {
	    return Utils.memtoul(m_Record.getBytes(FIELD_TOTAL + index), 10);
	}
	return 0;

    }

    public final int getNumItemsByDetail(DocDetail docDetail) {
	if (m_Details.size() > 0) {
	    return getNumItemsByDetail(m_Details.indexOf(docDetail));
	}
	return 0;
    }
    
    /**
     * LECTURA/ESCRITURA
     * 
     */   
    public final boolean empty(int indexField) {
	return m_Record.empty(DocHeader.FIELD_TOTAL + m_Details.size() + indexField);
    }

    public final void set(int indexField, final byte[] line, int start, int count) {
	m_Record.set(DocHeader.FIELD_TOTAL + m_Details.size() + indexField, 
		     line, start, count);
    }
    
    public final void set(int indexField, final byte[] line) {
	set(indexField, line, 0, line.length);
    }
    
    public final void set(int indexField, final String value) {
	m_Record.set(DocHeader.FIELD_TOTAL + m_Details.size() + indexField, value);
    }

    public final void set(int indexField, int value, int base) {
	m_Record.set(DocHeader.FIELD_TOTAL + m_Details.size() + indexField, 
		     value, base);
    }

    public final void set(int indexField, double value) {
	m_Record.set(DocHeader.FIELD_TOTAL + m_Details.size() + indexField, value);
    }
        
    public final byte[] getBytes(int indexField){
	return m_Record.getBytes(DocHeader.FIELD_TOTAL + m_Details.size() + indexField);
    }
    
    public final String getString(int indexField){
	return m_Record.getString(DocHeader.FIELD_TOTAL + m_Details.size() + indexField);
    }

    /**
     * ALMACENAMIENTO
     * 
     */
    private int getNextRecordId() {
	int ret;
	StoreTxt table;
	ret = StoreTxtId.INVALID;
	table = StoreTxt.create(m_Simlet, m_Filename, true);
	if (table != null) {
	    ret = table.headGetNextId();
	    table.close();
	}

	return ret;
    }

    protected boolean save() {
	StoreTxt table;
	Enumeration e;
	DocDetail docDetail;
	boolean ret;
	
	ret = true;
	
	setPrimaryKey();
	setCreateAge();
	setNumArchDetails();

	if (modified()) {

	    // Establecer el número de items de cada archivo de detalle.
	    setNumItemsByDetail();

	    // Guardar todos los archivos de detalles
	    e = m_Details.elements();
	    while (e.hasMoreElements()) {
		docDetail = (DocDetail)e.nextElement();
		if (!docDetail.save()) {
		    ret = false;
		    break;
		}
	    }
	
	    // Guardar cabecera.
	    if (ret) {
		ret = false;
		table = StoreTxt.create(m_Simlet, m_Filename, true);
		if (table != null) {
		    setUpdateAge();                    
		    if (table.save(m_Record)) {
			ret = true;
			m_Record.setModified(false);
		    }
		    table.close();
		}
	    }
	}
	
	return ret;
    }

    protected boolean load() {
	return true;
    }

    public boolean modified() {
	Enumeration e;
	DocDetail docDetail;
	
	if (!m_Record.modified()) {
	    if (m_Details.size() > 0) {
		e = m_Details.elements();
		while (e.hasMoreElements()) {
		    docDetail = (DocDetail)e.nextElement();
		    if (docDetail.modified()) {
			return true;
		    }
		}
	    }
	    return false;
	}

	return true;
    }        

}
